#pragma once

// 将线程封装起来，想要使用的时候就直接调用接口函数就行
// 不再需要调用底层接口

#include <iostream>
#include <string>
#include <cstring>
#include <cassert>
#include <functional>
#include <pthread.h>

namespace ThreadNs
{
    typedef std::function<void *(void *)> func_t;
    const int num = 1024;

    class Thread
    {
        private:
        // 在类内创建线程所对应的执行方法，需要将方法设置为static 
        // 为啥呢？ -- 因为类内的成员函数自带this指针 而静态函数就不包含this指针
        static void* start_routine(void*args)
        {
            // 安全的类型转换
            Thread *_this = static_cast<Thread *>(args);
            // 因为没有this指针 -- 所以拿不到类内的成员
            // 于是定义一个函数来拿
            return _this->callback();
        }
    public:
        Thread()
        {
            char namebuffer[num];
            // 往namebuffer中写入thread - %d
            snprintf(namebuffer, sizeof namebuffer, "thread - %d", threadnum++);
            name_ = namebuffer;
        }

        // 将创建和退出进行封装 后续只需要调用start和join接口即可
        void start(func_t func, void *args = nullptr)
        {
            func_ = func;
            args_ = args;
            int n = pthread_create(&tid_, nullptr, start_routine, this);
            assert(n);
            (void)n;
        }

        void join()
        {
            int n = pthread_join(tid_,nullptr);
            assert(n==0);
            (void)n;
        }

        std::string threadname()
        {
            return name_;
        }

        ~Thread()
        {
            // do nothing
        }

        // 拿到func_和args_
        void* callback()
        {
            return func_(args_);
        }

    private:
        std::string name_; // 线程名字
        func_t func_;
        void *args_; // 传入参数
        pthread_t tid_;

        static int threadnum; // 静态成员变量不能在内部直接定义
    };

    int Thread::threadnum = 1; // 在外部定义
}